package com.letu.core.dynamic;

import com.letu.annotation.annotation.vo.VoInfo;
import com.letu.annotation.model.BaseVoGroupClass;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;

/**
 * 精简VO参数核心功能
 * ligang 2020/03/20
 */
public class DynamicAnno {
    private static final Logger logger = LoggerFactory.getLogger(DynamicAnno.class);

    /**
     * 精简VO实体
     *
     * @param obj ligang 2020/03/20
     */
    public static Object executeSimplVo(Object obj) {
        try {
            if (obj == null) {
                return obj;
            }
            //JAVA泛型
//            Class c = FieldTypeUtil.getClassByFidldType(obj.getClass());
            Class c = FieldTypeUtil.getClassByJavaGenericity(obj.getClass());
            if (c == null) {
                //VO业务类
                if (FieldTypeUtil.getClassByBusinList(obj.getClass()) != null) {
                    //业务对象
                    disposeDataByResponBody(obj);
                }
            } else {
                if (FieldType.LIST.getTargerClazz().getName().equals(c.getName())) {
                    List list = (List) obj;
                    //List数组
                    list.forEach((s -> {
                        Class childClass = FieldTypeUtil.getClassByJavaGenericity(s.getClass());
                        if (childClass == null && FieldTypeUtil.getClassByBusinList(s.getClass()) != null) {
                            disposeDataByResponBody(s);
                        }
                    }));

                } else if (FieldType.SET.getTargerClazz().getName().equals(c.getName())) {
                    //Set数组
                } else {
                    //非业务对象，也非对象，可能就是java基本类型
                }
            }
            DynamicData.removeThreadData();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("精简VO实体失败");
            DynamicData.removeThreadData();
            return obj;
        }
    }


    /**
     * 是否在分组类里
     *
     * @param classes
     * @param aClass
     * @return
     */
    public static boolean isIncludeClass(Class[] classes, Class aClass) {
        for (Class class2 : classes) {
            if (aClass == null) {
                return true;
            }
            if (class2.getName().equals(aClass.getName())) {
                return true;
            }
            //all代表显示全部
            if (class2.getName().equals(BaseVoGroupClass.all.class.getName())) {
                return true;
            }
        }
        return false;
    }


    /**
     * 粗暴清空没有标识的属性
     *
     * @param fields
     */
    public static void delNull(Field[] fields, Object obj) {
        try {
//            //类上有自定义注解，全部返回，不用循环属性
//            VoInfo voInfoClass = obj.getClass().getAnnotation(VoInfo.class);
//            if (voInfoClass != null) {
//                for (Class class2 : voInfoClass.groups()) {
//                    //all代表显示全部
//                    if (class2.getName().equals(BaseVoGroupClass.all.class.getName())) {
//                        return;
//                    }
//                }
//            }

            //类上有自定义注解，全部返回，不用循环属性
            Boolean isAll = false;
            VoInfo voInfoClass = obj.getClass().getAnnotation(VoInfo.class);
            if (voInfoClass != null) {
                for (Class class2 : voInfoClass.groups()) {
                    //all代表显示全部
                    if (class2.getName().equals(BaseVoGroupClass.all.class.getName())) {
                        isAll = true;
                    }
                }
            }

            //清空没有标识的数据
            for (Field field : fields) {
                VoInfo voInfo1 = field.getAnnotation(VoInfo.class);
                if (voInfo1 == null || !isIncludeClass(voInfo1.groups(), DynamicData.getGroupClassThreadLocal())) {
                    if(!isAll){
                        DynamicProxy.voInvokSetByField(field, obj);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 赋值有标识但为空的数据
     *
     * @param fields
     */
    public static void updateNull(Field[] fields, Object obj) {
        try {

            //赋值有标识但为空的数据
            for (Field field : fields) {
                VoInfo voInfo1 = field.getAnnotation(VoInfo.class);
                if (voInfo1 != null && isIncludeClass(voInfo1.groups(), DynamicData.getGroupClassThreadLocal())) {
//                    DynamicProxy.voInvokSetNotNullByField(field, obj);
                    JsonInclude jsonInclude = field.getAnnotation(JsonInclude.class);
                    if(jsonInclude!=null){
                        //获取 foo 这个代理实例所持有的 InvocationHandler
                        InvocationHandler h = Proxy.getInvocationHandler(jsonInclude);

                        // 获取 AnnotationInvocationHandler 的 memberValues 字段
                        Field hField = null;
                        try {
                            hField = h.getClass().getDeclaredField("memberValues");
                            // 因为这个字段事 private final 修饰，所以要打开权限
                            hField.setAccessible(true);
                            // 获取 memberValues
                            Map memberValues = (Map) hField.get(h);
                            // 修改 value 属性值
                            memberValues.put("value", JsonInclude.Include.ALWAYS);
                            // 获取 foo 的 value 属性值
//                            JsonInclude.Include value = jsonInclude.value();
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }


                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 是否为VO标识类
     *
     * @param class2
     * @return
     */
    public static boolean isVoInfoClass(Class class2) {
        Field[] fields = class2.getDeclaredFields();
        for (Field field : fields) {
            VoInfo voInfo1 = field.getAnnotation(VoInfo.class);
            if (voInfo1 != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * Vo处理清空对象非必须属性
     *
     * @param obj
     */
    public static Object disposeDataByResponBody(Object obj) {

        //如果遇到Enum类，不处理
        if ("java.lang.Enum".equals(obj.getClass().getSuperclass().getName())) {
            return obj;
        }

        Field[] fields = obj.getClass().getDeclaredFields();

        //赋值有标识但为空的数据
        updateNull(fields, obj);


        //清空没有标识的数据
        delNull(fields, obj);
        //有标识的深入清空
        for (Field field : fields) {
            VoInfo voInfo1 = field.getAnnotation(VoInfo.class);
            if (voInfo1 != null && isIncludeClass(voInfo1.groups(), DynamicData.getGroupClassThreadLocal())) {
                if (FieldType.LIST.getTargerClazz().getName().equals(field.getType().getName())) {
                    //List数组
                    List list = (List) DynamicProxy.voInvokGetlByField(field, obj);
                    if (list != null) {
                        list.forEach((s -> {
                            Class childClass = FieldTypeUtil.getClassByJavaGenericity(s.getClass());
                            if (childClass == null && FieldTypeUtil.getClassByBusinList(s.getClass()) != null) {
                                disposeDataByResponBody(s);
                            }
                        }));
                    }

                } else if (FieldType.SET.getTargerClazz().getName().equals(field.getType().getName())) {
                    //Set数组

                } else if (FieldTypeUtil.getClassByBusinList(field.getType()) != null) {
                    //获取值
                    Object objectData = DynamicProxy.voInvokGetlByField(field, obj);
                    if (objectData != null) {
                        executeSimplVo(objectData);
                        //赋值
                        DynamicProxy.voInvokSetByField(field, obj, objectData);
                    }

                }
            }
        }
        return obj;
    }

}
